﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Timers;
using Microsoft.Kinect;
using Microsoft.Kinect.Toolkit;
using Microsoft.Samples.Kinect.WpfViewers;
using System.ComponentModel;
using Fizbin.Kinect.Gestures.Segments;
using Fizbin.Kinect.Gestures;
using ProjectSnooze;
using System.Windows.Threading;

namespace AlarmClock
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        

        //Kinect field
        public event PropertyChangedEventHandler PropertyChanged;
        private readonly KinectSensorChooser sensorChooser = new KinectSensorChooser();
        private GestureController gestureController;
        private Skeleton[] skeletons = new Skeleton[0];
        public static readonly DependencyProperty KinectSensorManagerProperty =
            DependencyProperty.Register(
                "KinectSensorManager",
                typeof(KinectSensorManager),
                typeof(MainWindow),
                new PropertyMetadata(null));
        private string gesture;
        
        DispatcherTimer refreshTimer;
        ColinWatch colinWatch;
        public string filename = "C:/Users/gebruiker/Dropbox/INF1A Periode 4/Audio Files/Wake Up! Daily Routines Song for Kids.wav";
         
        public MainWindow()
        {
            this.InitializeComponent();

            //Form setup
            SelectBtn.Visibility = Visibility.Hidden;
            PlaySoundTextBox.Visibility = Visibility.Hidden;
            SetAlarmGrid.Visibility = Visibility.Hidden;
            AlarmDot.Visibility = Visibility.Hidden;
            Cancel_Alarm.Visibility = Visibility.Hidden;
            TimeSetLabel.Content = "";
            
            //Timer
            DispatcherTimer updateTime = new DispatcherTimer();
            updateTime.Tick += new EventHandler(updateTime_Tick);
            updateTime.Interval = new TimeSpan(1500);
            updateTime.Start();

            //Kinect
            DataContext = this;
            InitializeComponent();
            KinectSensorManager = new KinectSensorManager();
            KinectSensorManager.KinectSensorChanged += this.KinectSensorChanged;
            sensorChooser.Start(); //Start Kinect
            var kinectSensorBinding = new Binding("Kinect") { Source = this.sensorChooser };
            BindingOperations.SetBinding(this.KinectSensorManager, KinectSensorManager.KinectSensorProperty, kinectSensorBinding);

            //2e timer setup
            refreshTimer = new DispatcherTimer();
            refreshTimer.Tick += new EventHandler(refreshTimer_Tick);
            refreshTimer.Interval = new TimeSpan(2500);
        }
        
        private void refreshTimer_Tick(object sender, EventArgs e)
        {
            Gesture = "";
            refreshTimer.Stop();
        }

        #region Kinect Default Methods

        private void OnSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
        {
            using (SkeletonFrame frame = e.OpenSkeletonFrame())
            {
                if (frame == null)
                    return;

                // resize the skeletons array if needed
                if (skeletons.Length != frame.SkeletonArrayLength)
                    skeletons = new Skeleton[frame.SkeletonArrayLength];

                // get the skeleton data
                frame.CopySkeletonDataTo(skeletons);

                foreach (var skeleton in skeletons)
                {
                    // skip the skeleton if it is not being tracked
                    if (skeleton.TrackingState != SkeletonTrackingState.Tracked)
                        continue;

                    // update the gesture controller
                    gestureController.UpdateAllGestures(skeleton);
                }
            }
        }

        private void KinectSensorChanged(object sender, KinectSensorManagerEventArgs<KinectSensor> args)
        {
            if (null != args.OldValue)
                UninitializeKinectServices(args.OldValue);

            if (null != args.NewValue)
                InitializeKinectServices(KinectSensorManager, args.NewValue);
        }

        private void InitializeKinectServices(KinectSensorManager kinectSensorManager, KinectSensor sensor)
        {
            // Application should enable all streams first.

            //color stream
            //kinectSensorManager.ColorFormat = ColorImageFormat.RgbResolution640x480Fps30;
            //kinectSensorManager.ColorStreamEnabled = true;

            //depth stream
            kinectSensorManager.DepthStreamEnabled = true;

            kinectSensorManager.TransformSmoothParameters =
                new TransformSmoothParameters
                {
                    Smoothing = 0.5f,
                    Correction = 0.5f,
                    Prediction = 0.5f,
                    JitterRadius = 0.05f,
                    MaxDeviationRadius = 0.04f
                };

            // start skeleton stream
            sensor.SkeletonFrameReady += OnSkeletonFrameReady;
            kinectSensorManager.SkeletonStreamEnabled = true;

            kinectSensorManager.KinectSensorEnabled = true;

            if (!kinectSensorManager.KinectSensorAppConflict)
            {
                gestureController = new GestureController();
                gestureController.GestureRecognized += OnGestureRecognized;

                //register gestures
                RegisterGestures();
            }
        }

        /// <summary>
        /// Kinect enabled apps should uninitialize all Kinect services that were initialized in InitializeKinectServices() here.
        /// </summary>
        /// <param name="sensor"></param>
        private void UninitializeKinectServices(KinectSensor sensor)
        {
            // unregister the event handlers
            sensor.SkeletonFrameReady -= OnSkeletonFrameReady;
            gestureController.GestureRecognized -= OnGestureRecognized;
        }

        public KinectSensorManager KinectSensorManager
        {
            get { return (KinectSensorManager)GetValue(KinectSensorManagerProperty); }
            set { SetValue(KinectSensorManagerProperty, value); }
        }

        #endregion Kinect Setup

        #region Gestures

        private void RegisterGestures()
        {
            IRelativeGestureSegment[] swipeleftSegments = new IRelativeGestureSegment[3];
            swipeleftSegments[0] = new SwipeLeftSegment1();
            swipeleftSegments[1] = new SwipeLeftSegment2();
            swipeleftSegments[2] = new SwipeLeftSegment3();
            gestureController.AddGesture("SwipeLeft", swipeleftSegments);

            IRelativeGestureSegment[] swiperightSegments = new IRelativeGestureSegment[3];
            swiperightSegments[0] = new SwipeRightSegment1();
            swiperightSegments[1] = new SwipeRightSegment2();
            swiperightSegments[2] = new SwipeRightSegment3();
            gestureController.AddGesture("SwipeRight", swiperightSegments);

            IRelativeGestureSegment[] waveRightSegments = new IRelativeGestureSegment[6];
            WaveRightSegment1 waveRightSegment1 = new WaveRightSegment1();
            WaveRightSegment2 waveRightSegment2 = new WaveRightSegment2();
            waveRightSegments[0] = waveRightSegment1;
            waveRightSegments[1] = waveRightSegment2;
            waveRightSegments[2] = waveRightSegment1;
            waveRightSegments[3] = waveRightSegment2;
            waveRightSegments[4] = waveRightSegment1;
            waveRightSegments[5] = waveRightSegment2;
            gestureController.AddGesture("WaveRight", waveRightSegments);

            IRelativeGestureSegment[] waveLeftSegments = new IRelativeGestureSegment[6];
            WaveLeftSegment1 waveLeftSegment1 = new WaveLeftSegment1();
            WaveLeftSegment2 waveLeftSegment2 = new WaveLeftSegment2();
            waveLeftSegments[0] = waveLeftSegment1;
            waveLeftSegments[1] = waveLeftSegment2;
            waveLeftSegments[2] = waveLeftSegment1;
            waveLeftSegments[3] = waveLeftSegment2;
            waveLeftSegments[4] = waveLeftSegment1;
            waveLeftSegments[5] = waveLeftSegment2;
            gestureController.AddGesture("WaveLeft", waveLeftSegments);
        }

        public String Gesture
        {
            get { return gesture; }

            private set
            {
                if (gesture == value)
                    return;

                gesture = value;

                if (this.PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs("Gesture"));
            }
        }

        private void OnGestureRecognized(object sender, GestureEventArgs e)
        {
            if (colinWatch != null)
            {
                if (colinWatch.alarmGoneWild == true)
                {
                    if ((e.GestureName == "WaveRight") || (e.GestureName == "WaveLeft"))
                    {
                        Console.WriteLine("Wave");
                        colinWatch.SnoozeWatch(1);
                    }
                    else if((e.GestureName == "SwipeRight") || (e.GestureName == "SwipeLeft"))
                    {
                        colinWatch.Stop();
                        AlarmDot.Visibility = Visibility.Hidden;
                        Cancel_Alarm.Visibility = Visibility.Hidden;
                        TimeSetLabel.Content = "";
                    }
                    refreshTimer.Start();
                }
            }
        }
        #endregion Gestures

        #region Form

        private void SetAlarmHour_TextChanged(object sender, TextChangedEventArgs e)
        {
        }

        private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            try
            {
                KinectSensorManager.ElevationAngle = Convert.ToInt32(angleSlider.Value);
            }
            catch
            {

            }
        }

        private void updateTime_Tick(object sender, EventArgs e)
        {
            //Time and date
            DateTime now = DateTime.Now;
            ClockTime.Content = now.ToShortTimeString();
            ClockDate.Content = now.ToShortDateString();
        }

        private void setAlarmVisible()
        {
            if (SetAlarmGrid.Visibility == Visibility.Visible)
            {
                SetAlarmGrid.Visibility = Visibility.Hidden;
            }
            else
            {
                SetAlarmGrid.Visibility = Visibility.Visible;
                if (DateTime.Now.Hour < 10)
                {
                    SetAlarmHour.Text = "0" + DateTime.Now.Hour.ToString();
                }
                else
                {
                    SetAlarmHour.Text = DateTime.Now.Hour.ToString();
                }

                if (DateTime.Now.Minute < 10)
                {
                    Console.WriteLine(SetAlarmMinute.Text = "0" + DateTime.Now.Minute.ToString());
                }
                else
                {
                    SetAlarmMinute.Text = DateTime.Now.Minute.ToString();
                    Console.WriteLine(DateTime.Now.Minute);
                }
            }
        }



        private void ExitBtn_Click(object sender, RoutedEventArgs e)
        {
            if (colinWatch != null)
            {
                colinWatch.LightsOff(); //lichten uit, anders blijven ze aan
            }
            this.Close();
        }

        private void SelectBtn_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
            // Set filter for file extension and default file extension 
            //dlg.DefaultExt = ".txt";
            //dlg.Filter = "Wav Files (*.WAV) |*.wav";
            dlg.Filter = "Mp3 (*.mp3)|*.mp3";

            // Display OpenFileDialog by calling ShowDialog method 
            Nullable<bool> result = dlg.ShowDialog();

            // Get the selected file name and display in a TextBox 
            if (result == true)
            {
                // Open document 
                filename = dlg.FileName.ToString();
                PlaySoundTextBox.Text = filename;
            }
        }

        private void PlayCheckBox(object sender, RoutedEventArgs e)
        {
            if (soundCheck.IsChecked == true)
            {
                SelectBtn.Visibility = Visibility.Visible;
                PlaySoundTextBox.Visibility = Visibility.Visible;
            }
            if (soundCheck.IsChecked == false)
            {
                SelectBtn.Visibility = Visibility.Hidden;
                PlaySoundTextBox.Visibility = Visibility.Hidden;
            }
        }

        private void btnSetAlarm_Click(object sender, RoutedEventArgs e)
        {
            setAlarmVisible();
        }

        private void btnTimeSet_Click(object sender, RoutedEventArgs e)
        {
            SetAlarmGrid.Visibility = Visibility.Hidden;
            AlarmDot.Visibility = Visibility.Visible;
            Cancel_Alarm.Visibility = Visibility.Visible;
            string setTimeString = SetAlarmHour.Text + ":" + SetAlarmMinute.Text;
            TimeSetLabel.Content = "Timeset " + setTimeString;
            colinWatch = new ColinWatch(int.Parse(SetAlarmHour.Text), int.Parse(SetAlarmMinute.Text), filename);
        }

        private void Cancel_Alarm_Click(object sender, RoutedEventArgs e)
        {
            AlarmDot.Visibility = Visibility.Hidden;
            Cancel_Alarm.Visibility = Visibility.Hidden;
            TimeSetLabel.Content = "";
            colinWatch.Stop();
        }

        private void cancelAlarm()
        {

        }

        #endregion form
    }
}